namespace Aob.Lite

import System

import Boo.Lang.Compiler
import Boo.Lang.Compiler.Ast
import Boo.Lang.Compiler.TypeSystem

[AttributeUsage(AttributeTargets.Method)]
class AdviceAttribute(Boo.Lang.Compiler.AbstractAstAttribute):
"""Description of AdviceAttribute"""

	_pointcut as ReferenceExpression
	_adviceMethod as Method

	def constructor([required] pointcut as ReferenceExpression):
		_pointcut = pointcut

	override def Apply([required(node as Method)] node as Node):
		_adviceMethod = node

		// we have to wait until we have type information
		GetPipeline().AfterStep += Pipeline_AfterStep		

	def GetPipeline():
		return _context.Parameters.Pipeline

	def Pipeline_AfterStep(sender, args as CompilerStepEventArgs):
		if args.Step isa Steps.ProcessMethodBodies: 
			// all types and entities are resolved by now
			// we need to restore our context from the args
			_context = args.Context
			GetPipeline().AfterStep -= Pipeline_AfterStep
			ProcessAdvices()

	def ProcessAdvices():
		pointcutEntity = ResolvePointcutReference()
		adviceEntity   = GetEntity(_adviceMethod)
		
		_context.CompileUnit.Accept(AdviceTransformer(_context, pointcutEntity, adviceEntity, _adviceMethod))
		
	def ResolvePointcutReference():
		NameResolutionService.EnterNamespace(GetEntity(_adviceMethod))
		return ResolveMethodReference(_pointcut)
		
	def ResolveMethodReference(reference as ReferenceExpression):
		return NameResolutionService.ResolveQualifiedName(reference.ToCodeString())

